package com.io.commonlib.helper

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Environment
import android.util.Base64
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import java.io.*
import java.net.URL

/**
 * 文件操作工具类
 */
class FileHelper {
    private val TAG = FileHelper::class.java.simpleName

    private val tempStr = ".temp"

    /**
     * 读取文件的内容
     */
    fun getFileContent(file: File): String {
        var content = ""
        if (!file.isDirectory && file.exists()) {
            if (file.name.endsWith("txt")) {
                val inStream = FileInputStream(file)
                inStream?.let {
                    val inputReader = InputStreamReader(inStream, "UTF-8")
                    val bufferedReader = BufferedReader(inputReader)
                    var line: String?
                    while (bufferedReader.readLine().also { line = it } != null) {
                        content += line + "\n"
                    }
                    inStream.close()
                }
            }
        }
        return content
    }

    /**
     * 下载文件
     */
    fun downloadFile(resourceUrl: String, localUrl: String) {
        if (resourceUrl.isNotEmpty() && localUrl.isNotEmpty()) {
            runBlocking(Dispatchers.IO) {
                try {
                    if (resourceUrl.indexOf('.') != -1 && resourceUrl.indexOf('/') != -1) {
                        val fileName =
                            resourceUrl.substring(resourceUrl.lastIndexOf('/') + 1)
                        var finalLocalUrl = ""
                        if(localUrl.lastIndexOf("/") != localUrl.length-1){
                            finalLocalUrl = "${localUrl}/"
                        } else {
                            finalLocalUrl = localUrl
                        }
                        val file = File(finalLocalUrl + fileName)
                        val parentFile = file.parentFile
                        LogHelper.d(TAG, "parentFile是否为空:${parentFile == null}")
                        if (!parentFile.exists()) {
                            parentFile.mkdirs()
                        }
                        if (!file.exists()) {
                            var oldFile = File(finalLocalUrl + fileName)
                            val tmpFile = File(finalLocalUrl + fileName + tempStr)
                            if (tmpFile.exists()) {
                                LogHelper.d(
                                    TAG,
                                    "downloadFile -- 临时文件存在"
                                )
                                tmpFile.delete()
                                download(resourceUrl, finalLocalUrl)
                            } else if(oldFile.exists()){
                                LogHelper.d(TAG, "文件已经存在，不再下载")
                            } else {
                                LogHelper.d(
                                    TAG,
                                    "downloadFile -- 文件都不存在，准备下载"
                                )
                                tmpFile.createNewFile()
                                download(resourceUrl, finalLocalUrl)
                            }
                        } else {
                            LogHelper.d(
                                TAG,
                                "downloadFile -- 原文件存在"
                            )
                        }
                    } else {
                        LogHelper.d(
                            TAG,
                            "downloadFile -- 文件路径不合法"
                        )
                    }
                } catch (e: Exception) {
                    LogHelper.e(TAG, "downloadFile--Exception:${e.message}")
                }
            }
        }

    }

    /**
     * 下载阿里云OSS上的文件
     */
    fun downloadOSSFile(resourceUrl: String, localUrl: String, fileName: String) {
        if (resourceUrl.isNotEmpty() && localUrl.isNotEmpty() && fileName.isNotEmpty()) {
            runBlocking(Dispatchers.IO) {
                try {
                    var finalLocalUrl = ""
                    if(localUrl.lastIndexOf("/") != localUrl.length-1){
                        finalLocalUrl = "${localUrl}/"
                    } else {
                        finalLocalUrl = localUrl
                    }
                    val file = File(finalLocalUrl + fileName)
                    val parentFile = file.parentFile
                    LogHelper.d(TAG, "parentFile是否为空:${parentFile == null}")
                    if (!parentFile.exists()) {
                        parentFile.mkdirs()
                    }
                    if (!file.exists()) {
                        var oldFile = File(finalLocalUrl + fileName)
                        val tmpFile = File(finalLocalUrl + fileName + tempStr)
                        if (tmpFile.exists()) {
                            LogHelper.d(
                                TAG,
                                "downloadOSSFile -- 临时文件存在"
                            )
                            tmpFile.delete()
                            downloadOSS(resourceUrl, finalLocalUrl, fileName)
                        } else if(oldFile.exists()){
                            LogHelper.d(TAG, "文件已经存在，不再下载")
                        } else {
                            LogHelper.d(
                                TAG,
                                "downloadOSSFile -- 文件都不存在，准备下载"
                            )
                            tmpFile.createNewFile()
                            downloadOSS(resourceUrl, finalLocalUrl, fileName)
                        }
                    } else {
                        LogHelper.d(
                            TAG,
                            "downloadOSSFile -- 原文件存在"
                        )
                    }
                } catch (e: Exception) {
                    LogHelper.e(TAG, "downloadOSSFile--Exception:${e.message}")
                }
            }
        }

    }


    /**
     * 删除多个文件
     * @param filePathList
     */
    fun deleteFiles(filePathList: MutableList<String>, localUrl: String) {
        if (filePathList.isNotEmpty() && localUrl.isNotEmpty()) {
            for (filePath in filePathList) {
                if (filePath.isNotEmpty()) {
                    val localPath =
                        (localUrl
                                + filePath.substring(filePath.lastIndexOf("/") + 1))
                    val file = File(localPath)
                    if (file.exists()) {
                        file.delete()
                    } else {
                        val localPathTmp =
                            (localUrl
                                    + filePath.substring(
                                filePath.lastIndexOf("/") + 1
                            ) + tempStr)
                        val fileTmp = File(localPathTmp)
                        if (fileTmp.exists()) {
                            fileTmp.delete()
                        }
                    }
                }
            }
        }
    }

    /**
     * 删除指定文件
     */
    fun deleteFile(localFilePath: String){
        if(localFilePath.isNotEmpty()){
            val file = File(localFilePath)
            if(file.exists()){
                file.delete()
            } else {
                LogHelper.i(TAG, "${localFilePath}--文件不存在，无法删除")
            }
        }
    }

    /**
     * 删除指定目录下所有的文件
     */
    fun deleteAllFiles(path: String) {
        val files = File(path)
        if (files.exists() && files.isDirectory) {
            for (file in files.listFiles()) {
                if (file.isFile) {
                    file.delete()
                } else if (file.isDirectory) {
                    deleteAllFiles(file.absolutePath)
                }
            }
        }
    }

    /**
     * 获取指定文件路径的文件后缀
     * @param filePath
     * @return
     */
    fun getFileSuffix(filePath: String): String {
        var result = ""
        if (filePath.isNotEmpty() && filePath.contains(".")
            && filePath.lastIndexOf(".") != filePath.length - 1) {
            result = filePath.substring(filePath.lastIndexOf("."))
        }
        return result
    }

    fun byteToFile(contents: ByteArray?, filePath: String) {
        var bis: BufferedInputStream? = null
        var fos: FileOutputStream? = null
        var output: BufferedOutputStream? = null
        try {
            val byteInputStream =
                ByteArrayInputStream(contents)
            bis = BufferedInputStream(byteInputStream)
            val file = File(filePath)
            // 获取文件的父路径字符串
            val path = file.parentFile
            if (!path.exists()) {
                LogHelper.d(
                    TAG,
                    "文件夹不存在，创建。path=$path"
                )
                val isCreated = path.mkdirs()
                if (!isCreated) {
                    LogHelper.e(
                        TAG,
                        "创建文件夹失败，path=$path"
                    )
                }
            }
            if (file.exists()) {
                file.delete()
            }
            fos = FileOutputStream(file)
            // 实例化OutputString 对象
            output = BufferedOutputStream(fos)
            val buffer = ByteArray(1024)
            var length = bis.read(buffer)
            while (length != -1) {
                output.write(buffer, 0, length)
                length = bis.read(buffer)
            }
            output.flush()
        } catch (e: Exception) {
            LogHelper.e(
                TAG,
                "输出文件流时抛异常，filePath=" + filePath
                        + "; Exception:" + e.message
            )
        } finally {
            try {
                bis?.close()
                fos?.close()
                output?.close()
            } catch (e0: IOException) {
                LogHelper.e(
                    TAG,
                    "文件处理失败，filePath=" + filePath
                            + "; Exception:" + e0.message
                )
            }
        }
    }

    /**
     * 把一个文件转化为byte字节数组。
     *
     * @return
     */
    fun fileConvertToByteArray(file: File): ByteArray? {
        var data: ByteArray? = null
        try {
            if(file.exists()){
                val fis = FileInputStream(file)
                val baos = ByteArrayOutputStream(file.length().toInt())
                var len: Int
                val buffer = ByteArray(1024)
                while (fis.read(buffer).also { len = it } != -1) {
                    baos.write(buffer, 0, len)
                }
                data = baos.toByteArray()
                fis.close()
                baos.close()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return data
    }

    /**
     * 根据文件路径获取文件名字
     */
    fun getFileName(filePath: String): String{
        return filePath.substring(filePath.lastIndexOf("/") + 1)
    }

    /**
     * 重命名文件
     */
    fun reNameFile(filePath: String, newName: String){
        try {
            val oldName = getFileName(filePath)
            if(oldName != newName){
                val file = File(filePath)
                val oldFileFolder = filePath.substring(0, filePath.lastIndexOf("/") + 1)
                file.renameTo(File(oldFileFolder + newName))
            }
        } catch (e: Exception) {
            LogHelper.e(TAG, "reNameFile--Exception:${e.message}")
        }
    }

    /**
     * 本地路径转图片
     * @param path
     * @return
     */
    fun pathToBitmap(path: String): Bitmap? {
        return try {
            BitmapFactory.decodeFile(path)
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }

    /**
     * 获取指定目录下的所有文件
     */
    fun files(context: Context): Array<File> {
        val externalFilesDir = context.getExternalFilesDir(null)
        val file = File(externalFilesDir, "Face_Import")
        if (!file.exists()) {
            file.mkdirs()
        }
        val listFiles: Array<File> = file.listFiles()
        return listFiles
    }

    /*
     * 获取不带扩展名的文件名
     * */
    fun getFileNameNoSuffix(filename: String?): String? {
        if (filename != null && filename.length > 0) {
            val dot = filename.lastIndexOf('.')
            if (dot > -1 && dot < filename.length) {
                return filename.substring(0, dot)
            }
        }
        return filename
    }

    /**
     * 保存图片到指定路径
     * /storage/emulated/0/Android/data/com.jzqf.smart/files/PICTURES
     */
    fun saveImage(context: Context, bmp: Bitmap?): File? {
        if (bmp == null) {
            return null
        }
        val appDir = File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!.path)
        if (!appDir.exists()) {
            appDir.mkdirs()
        }
        val fileName = System.currentTimeMillis().toString() + ".jpg"
        val file = File(appDir, fileName)
        try {
            val fos = FileOutputStream(file)
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos)
            fos.flush()
            fos.close()
            return file
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
            return null
        } catch (e: IOException) {
            e.printStackTrace()
            return null
        }
    }

    fun base64ToBitmap(base64String: String): Bitmap? {
        val base64Str = Uri.decode(base64String)
        val decode = Base64.decode(base64Str, Base64.DEFAULT)
        return BitmapFactory.decodeByteArray(decode, 0, decode.size)
    }

    fun bitmapToBytes(bm: Bitmap): ByteArray? {
        val baos = ByteArrayOutputStream()
        bm.compress(Bitmap.CompressFormat.PNG, 100, baos)
        return baos.toByteArray()
    }

    //判断文件是否存在
    fun fileIsExists(strFile: String?): Boolean {
        try {
            val f = File(strFile)
            if (!f.exists()) {
                return false
            }
        } catch (e: java.lang.Exception) {
            return false
        }
        return true
    }
    //region 私有方法
    //下载的具体操作
    private fun download(remoteUrl: String, localUrl: String) {
        val fileName = remoteUrl.substring(remoteUrl.lastIndexOf('/') + 1)
        val filePath =
            "$localUrl/$fileName$tempStr"
        val filePath0 =
            "$localUrl/$fileName"
        val file = File(filePath0)
        if (!file.exists()) {
            try {
                val url = URL(remoteUrl)
                //打开连接
                val conn = url.openConnection()
                //打开输入流
                val input = conn.getInputStream()
                //获得长度
                //val contentLength = conn.contentLength

                //创建字节流
                val bs = ByteArray(1024)
                var len: Int
                val os: OutputStream = FileOutputStream(filePath)
                //写数据
                while (input.read(bs).also { len = it } != -1) {
                    os.write(bs, 0, len)
                }
                val file1 = File(filePath)
                val finalPath = filePath.replace(tempStr, "")
                file1.renameTo(File(finalPath))
                //完成后关闭流
                LogHelper.d(
                    TAG,
                    "下载成功！-------------$fileName"
                )
                os.close()
                input.close()
            } catch (e: Exception) {
                LogHelper.e(
                    TAG,
                    "下载失败！需要重新下载-------------" + e.message
                )
                //download(remoteUrl, localUrl)
            }
        }
    }

    //下载的具体操作
    private fun downloadOSS(remoteUrl: String, localUrl: String, fileName: String) {
        val filePath =
            "$localUrl/$fileName$tempStr"
        val filePath0 =
            "$localUrl/$fileName"
        val file = File(filePath0)
        if (!file.exists()) {
            try {
                val url = URL(remoteUrl)
                //打开连接
                val conn = url.openConnection()
                //打开输入流
                val input = conn.getInputStream()
                //获得长度
                //val contentLength = conn.contentLength

                //创建字节流
                val bs = ByteArray(1024)
                var len: Int
                val os: OutputStream = FileOutputStream(filePath)
                //写数据
                while (input.read(bs).also { len = it } != -1) {
                    os.write(bs, 0, len)
                }
                val file1 = File(filePath)
                val finalPath = filePath.replace(tempStr, "")
                file1.renameTo(File(finalPath))
                //完成后关闭流
                LogHelper.d(
                    TAG,
                    "下载成功！-------------$fileName"
                )
                os.close()
                input.close()
            } catch (e: Exception) {
                LogHelper.e(
                    TAG,
                    "下载失败！需要重新下载-------------" + e.message
                )
                //downloadOSS(remoteUrl, localUrl, fileName)
            }
        }
    }
    //endregion
}